from typing import List, Dict, Any, Optional
from .executor import AbstractExecutor, ExecutionContext, Tuple, Schema
from .seq_scan_executor import SeqScanExecutor
from .projection_executor import ProjectionExecutor
from .filter_executor import FilterExecutor
from .execution_engine import ExecutionEngine

class QueryPlan:
    """查询计划表示"""
    
    def __init__(self, plan_type: str, **kwargs):
        self.plan_type = plan_type
        self.params = kwargs
        self.children: List[QueryPlan] = []
    
    def add_child(self, child: 'QueryPlan'):
        """添加子计划"""
        self.children.append(child)

class QueryExecutor:
    """查询计划执行器"""
    
    def __init__(self, context: ExecutionContext):
        self.context = context
    
    def execute(self, plan: QueryPlan) -> List[Tuple]:
        """执行查询计划"""
        executor = self._build_executor(plan)
        # 显式初始化执行器
        executor.init()
        results = []
        # 执行查询并收集结果
        while True:
            tuple_result = executor.next()
            if tuple_result is None:
                break
            results.append(tuple_result)
        return results
    
    def _build_executor(self, plan: QueryPlan) -> AbstractExecutor:
        """根据查询计划构建执行器"""
        if plan.plan_type == "seq_scan":
            table_name = plan.params["table_name"]
            schema = plan.params["schema"]
            return SeqScanExecutor(self.context, table_name,schema)
        elif plan.plan_type == "filter":
            predicate = plan.params["predicate"]
            child_executor = self._build_executor(plan.children[0])
            return FilterExecutor(self.context, child_executor, predicate)
        elif plan.plan_type == "projection":
            fields = plan.params["fields"]
            child_executor = self._build_executor(plan.children[0])
            return ProjectionExecutor(self.context, child_executor, fields)
        # elif plan.plan_type == "index_scan":
        #     table_name = plan.params["table_name"]
        #     schema = plan.params["schema"]
        #     index_name = plan.params["index_name"]
        #     search_key = plan.params.get("search_key")
        #     range_start = plan.params.get("range_start")
        #     range_end = plan.params.get("range_end")
        #     return IndexScanExecutor(
        #         self.context, table_name, schema, index_name,
        #         search_key, range_start, range_end
        #     )
        else:
            raise ValueError(f"Unknown plan type: {plan.plan_type}")